package com.pencilisland.pay.mgt.app.service.impl;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.pencilisland.pay.api.bean.constant.GoodsConstant;
import com.pencilisland.pay.api.bean.mp.core.CancelGoodsREQ;
import com.pencilisland.pay.api.bean.mp.core.CancelGoodsRES;
import com.pencilisland.pay.api.bean.mp.core.PublishGoodsREQ;
import com.pencilisland.pay.api.bean.mp.core.PublishGoodsRES;
import com.pencilisland.pay.api.bean.mp.core.WxappAccessTokenREQ;
import com.pencilisland.pay.api.bean.mp.core.WxappAccessTokenRES;
import com.pencilisland.pay.mgt.Vars;
import com.pencilisland.pay.mgt.app.entity.GoodsEntity;
import com.pencilisland.pay.mgt.app.entity.GoodsEntity_;
import com.pencilisland.pay.mgt.app.entity.GoodsImgEntity;
import com.pencilisland.pay.mgt.app.entity.TenantEntity;
import com.pencilisland.pay.mgt.app.repository.GoodsImgRepository;
import com.pencilisland.pay.mgt.app.repository.GoodsRepository;
import com.pencilisland.pay.mgt.app.repository.TenantRepository;
import com.pencilisland.pay.mgt.app.service.GoodsService;
import com.pencilisland.pay.mgt.app.service.RestService;
import com.pencilisland.pay.mgt.console.entity.SysUser;
import com.pencilisland.pay.mgt.console.service.UserService;
import com.pencilisland.pay.mgt.thirdparty.bean.UploadFile;
import com.pencilisland.pay.mgt.thirdparty.service.AliOssService;
import com.pencilisland.pay.mgt.util.RandomUtil;

@Component
public class GoodsServiceImpl implements GoodsService {
	Logger log = LoggerFactory.getLogger(getClass());

	@Autowired
	Vars vars;
	@Autowired
	GoodsRepository goodsRepo;
	@Autowired
	GoodsImgRepository goodsImgRepo;
	@Autowired
	TenantRepository tenantRepo;
	@Autowired
	RestService restService;
	@Autowired
	AliOssService aliOssService;
	@Autowired
	UserService userService;

	@Override
	public Page<GoodsEntity> goodsList(final GoodsEntity cretiria, int start, int limit) {

		Specification<GoodsEntity> spec = new Specification<GoodsEntity>() {

			@Override
			public Predicate toPredicate(Root<GoodsEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> list = new ArrayList<Predicate>();
				//判断是否是商户
				SysUser user = userService.findSessionUser();
				TenantEntity tenant = tenantRepo.findByUserId(user.getUserId());
				if(tenant!=null){
					list.add(cb.equal(root.get(GoodsEntity_.merchantId), tenant.getCode()));
				}
				if (!StringUtils.isEmpty(cretiria.getName())) {
					list.add(cb.like(root.get(GoodsEntity_.name), "%" + cretiria.getName() + "%"));
				}
				if (!StringUtils.isEmpty(cretiria.getCode())) {
					list.add(cb.equal(root.get(GoodsEntity_.code), cretiria.getCode()));
				}
				Predicate[] p = new Predicate[list.size()];
				return cb.and(list.toArray(p));
			}
		};

		Sort sort = new Sort(new Order(Sort.Direction.ASC, GoodsEntity_.weight.getName()),new Order(Sort.Direction.DESC, GoodsEntity_.code.getName()));

		Pageable pageable = new PageRequest(start/limit, limit, sort);

		return goodsRepo.findAll(spec, pageable);

	}

	@Override
	public GoodsEntity save(GoodsEntity goods) {
		if (goods.getId() == null) {
			goods.setStatus(GoodsConstant.STATUS_0);
			goods.setCreateTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
			goods.setCode(RandomUtil.genOrder("G", 16));
		} else {
			GoodsEntity exit = goodsRepo.findOne(goods.getId());
			goods.setStatus(exit.getStatus());
			goods.setCreateTime(exit.getCreateTime());
		}
		TenantEntity tenant = tenantRepo.findByUserId(goods.getUserId());
		if(tenant!=null)
			goods.setMerchantId(tenant.getCode());
		
		return goodsRepo.save(goods);
	}

	@Override
	public GoodsEntity loadData(Long id) {
		return goodsRepo.findOne(id);
	}

	@Override
	public void delete(Long id) {
		goodsRepo.delete(id);
	}

	@Override
	public void deleteImg(Long id) {
		goodsImgRepo.delete(id);
	}

	@Override
	public UploadFile[] imgs(Long goodsId,Integer type) {
		List<GoodsImgEntity> imgs = goodsImgRepo.findByGoodsIdAndTypeOrderByFileNameAsc(goodsId,type);
		if (imgs != null && !imgs.isEmpty()) {
			UploadFile[] result = new UploadFile[imgs.size()];
			for (int i = 0; i < imgs.size(); i++) {
				GoodsImgEntity img = imgs.get(i);
				UploadFile uploadFile = new UploadFile();
				uploadFile.setUrl(img.getUrl());
				uploadFile.setName(img.getFileName());
				uploadFile.setDeleteType("POST");
				uploadFile.setSize(img.getSize());
				uploadFile.setThumbnailUrl(img.getUrl() + "?x-oss-process=image/resize,w_80");
				uploadFile.setDeleteUrl(vars.getContext() + "/app/goods/img/delete/" + img.getId());
				result[i] = uploadFile;
			}
			return result;
		}
		return null;
	}

	@Override
	public void publish(Long goodsId) throws Exception {
		GoodsEntity goods = goodsRepo.findOne(goodsId);

		PublishGoodsREQ publishGoodsReq = new PublishGoodsREQ();
		publishGoodsReq.setCode(goods.getCode());
		publishGoodsReq.setMerchantId(goods.getMerchantId());
		publishGoodsReq.setName(goods.getName());
		publishGoodsReq.setPrice(goods.getPrice());
		publishGoodsReq.setRemark(goods.getRemark());
		publishGoodsReq.setStock(goods.getStock());
		publishGoodsReq.setWeight(goods.getWeight());
		publishGoodsReq.setFreePost(goods.getFreePost());

		List<GoodsImgEntity> goodsImgs = goodsImgRepo.findByGoodsIdOrderByTypeAscFileNameAsc(goodsId);
		if (goodsImgs != null && !goodsImgs.isEmpty()) {
			publishGoodsReq.setImgDetails(new ArrayList<PublishGoodsREQ.ElementImgDetails>());
			for (GoodsImgEntity goodsImg : goodsImgs) {
				PublishGoodsREQ.ElementImgDetails imgDetail = new PublishGoodsREQ.ElementImgDetails();
				imgDetail.setType(goodsImg.getType());
				imgDetail.setUrl(goodsImg.getUrl());
				publishGoodsReq.getImgDetails().add(imgDetail);
			}
		}

		PublishGoodsRES publishGoodsRes = restService.sendToCoreMP("publishGoods", publishGoodsReq,
				PublishGoodsRES.class);

		if (publishGoodsRes.getSuccess()) {
			goods.setStatus(GoodsConstant.STATUS_1);
			goodsRepo.save(goods);
			log.info("发布商品成功【{}】", goods.getCode());
		} else {
			log.info("发布商品失败【{}】,返回信息【{}】", goods.getCode(), publishGoodsRes.getMessage());
			throw new Exception(publishGoodsRes.getMessage());
		}
	}

	@Override
	public void cancel(Long goodsId) throws Exception {
		GoodsEntity goods = goodsRepo.findOne(goodsId);
		
		CancelGoodsREQ cancelGoodsReq = new CancelGoodsREQ();
		cancelGoodsReq.setCode(goods.getCode());
		
		CancelGoodsRES cancelGoodsRes = restService.sendToCoreMP("cancelGoods", cancelGoodsReq, CancelGoodsRES.class);
		
		if(cancelGoodsRes.getSuccess()){
			goods.setStatus(GoodsConstant.STATUS_0);
			goodsRepo.save(goods);
			log.info("撤销商品成功【{}】", goods.getCode());
		}else{
			log.info("撤销商品失败【{}】,返回信息【{}】", goods.getCode(), cancelGoodsRes.getMessage());
			throw new Exception(cancelGoodsRes.getMessage());
		}
	}

	@Override
	public String qrcode(Long goodsId) throws Exception {
		GoodsEntity goods = goodsRepo.findOne(goodsId);
		if(!StringUtils.isEmpty(goods.getQrcodeUrl())){
			return goods.getQrcodeUrl();
		}
		
		WxappAccessTokenREQ wxappAccessTokenReq = new WxappAccessTokenREQ();
		wxappAccessTokenReq.setPlaceholder("PH");
		WxappAccessTokenRES wxappAccessTokenRes = restService.sendToCoreMP("wxappAccessToken", wxappAccessTokenReq, WxappAccessTokenRES.class);
		if(wxappAccessTokenRes.getSuccess()){
			byte[] qrcodeBytes = restService.createwxaqrcode(wxappAccessTokenRes.getAccessToken(),"pages/goods/goods?goodsCode="+goods.getCode(),200);
			String url =aliOssService.put("pay/goods/"+goods.getCode()+"/qrcode.jpg", qrcodeBytes);
			goods.setQrcodeUrl(url);
			goodsRepo.save(goods);
		}else{
			throw new Exception(wxappAccessTokenRes.getMessage());
		}
		return goods.getQrcodeUrl();
	}

}
